package md.sv.dbu.utils;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.Map;

/**
 * @author MG
 */
public class DbuUtils {
    private static final Logger logger = LoggerFactory.getLogger(DbuUtils.class);

    private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    public static void UpdateVariables(Map<String, Object> variables, SqlParameterSource replacers) {
        for (String key : variables.keySet()) {
            if (replacers.hasValue(key)) {
                variables.put(key, replacers.getValue(key));
            }
        }
    }

    public static boolean fileExists(String fileName) {
        File file = new File(fileName);
        return (file.exists() && file.isFile());
    }

    public static String readFile(String fileName) {
        try {
            File file = new File(fileName);
            logger.info("Reading file: {}", file);
            return FileUtils.readFileToString(file, "UTF-8");
        } catch (IOException e) {
            logger.error("Could not read file: " + fileName, e);
        }
        return null;
    }

    public static void writeFile(String fileName, String content) {
        try {
            logger.info("Writing file: {}", fileName);
            File file = new File(fileName);
            FileUtils.writeStringToFile(file, content, "UTF-8");
        } catch (IOException e) {
            logger.error("Could not write file: " + fileName, e);
        }
    }

    public static Document openXmlDocument(File file) {
        DocumentBuilder builder = null;
        try {
            logger.info("Opening XML file: {}", file);
            builder = factory.newDocumentBuilder();
            return builder.parse(new BufferedInputStream(FileUtils.openInputStream(file)));
        } catch (Exception e) {
            logger.error("Could not open XML file: " + file, e);
        }
        return null;
    }

    public static Document getDocumentFromString(String document) {
        DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();
            return builder.parse(new ByteArrayInputStream(document.getBytes("UTF-8")));
        } catch (Exception e) {
            logger.error("Could not open XML Document from String", e);
        }
        return null;
    }

    public static String toString(Document doc) {
        try {
            StringWriter sw = new StringWriter();
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

            transformer.transform(new DOMSource(doc), new StreamResult(sw));
            return sw.toString();
        } catch (Exception ex) {
            throw new RuntimeException("Error converting to String", ex);
        }
    }

    public static InputStream getInputStream(String source) throws UnsupportedEncodingException {
        return new ByteArrayInputStream(source.getBytes("UTF-8"));
    }

    public static InputStream openFile(String fileName) throws IOException {
        return new BufferedInputStream(FileUtils.openInputStream(new File(fileName)));
    }
}
